package uk.ac.lkl.common.ui;



import java.awt.Color;
import java.awt.GridLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

import java.text.NumberFormat;

import javax.swing.JTextField;

import javax.swing.table.TableModel;


/**
 * A default view of a cell within a table model.
 * 
 * The row and column indices specified when constructed are immutable. This
 * means that this class can be used to render whatever values are apropriate
 * within the model.
 * 
 * @author Darren Pearce
 * @version $Revision$
 * @version $Date$
 * 
 */
public class CellView<O> extends View<O> {

    // hack making this public. Is so other classes can use this. Need to make
    // it a lot more robust.
    public static NumberFormat FORMAT;

    static {
        FORMAT = NumberFormat.getNumberInstance();
        FORMAT.setMaximumFractionDigits(2);
        FORMAT.setMinimumFractionDigits(0);
    }


    private JTextField textField;


    private TableModel tableModel;


    private int rowIndex;


    private int columnIndex;


    public CellView(TableModel tableModel, int rowIndex, int columnIndex,
            O model) {
        super(model);
        this.tableModel = tableModel;
        this.rowIndex = rowIndex;
        this.columnIndex = columnIndex;
        setLayout(new GridLayout(1, 1));
        textField = new JTextField();
        textField.setHorizontalAlignment(JTextField.RIGHT);
        add(textField);
        updateView();
        addListeners();
    }


    public void updateView() {
        O model = getModel();
        if (model == null)
            textField.setText("");
        else {
            // hack
            if (tableModel.getColumnClass(columnIndex) == Float.class)
                textField.setText(FORMAT.format((Float) model));
            else
                textField.setText(model.toString());
        }

        boolean editable = tableModel.isCellEditable(rowIndex, columnIndex);
        textField.setEnabled(editable);
    }


    private void addListeners() {
        addFocusListener();
        addActionListener();
    }


    private void addFocusListener() {
        textField.addFocusListener(new FocusAdapter() {

            public void focusLost(FocusEvent e) {
                processValue();
            }
        });
    }


    private void addActionListener() {
        textField.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                processValue();
            }
        });
    }


    private void processValue() {
        try {
            String textValue = textField.getText();

            Object value;

            if (textValue.length() == 0) {
                value = null;
            }
            else {
                // need to factor this out properly
                Class columnClass = tableModel.getColumnClass(columnIndex);
                if (columnClass == Float.class) {
                    value = Float.parseFloat(textValue);
                }
                else if (columnClass == Integer.class) {
                    value = Integer.parseInt(textValue);
                }
                else
                    value = textValue;
            }

            tableModel.setValueAt(value, rowIndex, columnIndex);
            textField.setForeground(Color.BLACK);
            updateView();
        }
        catch (NumberFormatException e) {
            textField.setForeground(Color.RED);
        }
    }
}
